#include "tcp_connection.h"

namespace eGear{

TcpConnection::TcpConnection(char *_addr, int _port){
	socketfd = -1;
	int addr_len = strlen(_addr)+1;
	addr = new char[addr_len];
	strcpy(addr, _addr);
	max_addr_len = addr_len;
	port = _port;
	
};

TcpConnection::TcpConnection(int _socketfd, struct sockaddr*_sockaddr,
		socklen_t _addrlen){
	socketfd = _socketfd;
	addr = NULL;
	max_addr_len = 0;
	port = 0;
	memcpy(&sockaddr, _sockaddr, _addrlen);
	if((stream = fdopen(socketfd, "rb+"))==NULL){
		perror("fdopen failed on the socket");
	};
};

TcpConnection::~TcpConnection(){
	if(addr!=NULL){
		delete addr;
	};
	if(socketfd!=-1){
		close(socketfd);
	};
};

int TcpConnection::connect(){
	if(addr==NULL){
		fprintf(stderr, "no aadress specified\n");
		return -1;
	}
	if(port==0){
		fprintf(stderr, "no port specified\n");
		return -1;
	};
	if(socketfd!=-1){
		// already a socket
		close(socketfd);
		socketfd = -1;
	};
	struct addrinfo hints, *result, *rp;
	char port_str[10];
	memset(&hints, 0, sizeof(struct addrinfo));
	hints.ai_family = AF_INET;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_flags = 0;
	hints.ai_protocol = 0;
	snprintf(port_str, 10, "%d", port);
	int s = getaddrinfo(addr, port_str, &hints, &result);
	if (s != 0) {
		// bad address format
		fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
               	return -1;
	}

	// we will try each address for connecting
	for (rp = result; rp != NULL; rp = rp->ai_next) {
		socketfd = socket(rp->ai_family, rp->ai_socktype,
			rp->ai_protocol);
		if (socketfd == -1){
					// failed to connect
			continue;
		}

		if (::connect(socketfd, rp->ai_addr, rp->ai_addrlen) != -1){
			break;      	  /* Success */
		}

		close(socketfd);
	}
	if (rp == NULL) {               /* No address succeeded */
		fprintf(stderr, "Could not connect\n");
		freeaddrinfo(result);
		return -1;
	}

	freeaddrinfo(result);  /* No longer needed */
	return 0;
};

int TcpConnection::readLine(void *buff, size_t count){
	return ::read(socketfd, buff, count);
};

int TcpConnection::write(void *buff, size_t count){
	return ::write(socketfd, buff, count);
};

int TcpConnection::setAddr(char *_addr){
	int new_addr_len = strlen(_addr)+1;
	if(addr != NULL && max_addr_len < new_addr_len){
		// the existing memory is too small
		delete addr;
		addr = NULL;
	}
	if(addr==NULL){
		addr = new char[new_addr_len];
		if(addr==NULL){
			perror("no memory");
			return -1;
		}
		max_addr_len = new_addr_len;
	}
	strcpy(addr, _addr);
	return 0;
};

};
